import { Tree, Dropdown, Menu, Space, message, Modal, Tooltip } from 'antd';
import styles from './style.less';
import { connect, Link, history } from 'umi';
import { useEffect, useState, useImperativeHandle, forwardRef } from 'react';
import { PlusOutlined, FileAddOutlined, FolderAddOutlined, CaretDownOutlined } from '@ant-design/icons'
import DirFormModal from './DirFormModal'
import { listDirs, updateDir } from '@/services/doc/common'
import ActionDropdown from '@/components/ActionDropdown'
import ArrayUtils from '@/utils/ArrayUtils'
import classNames from 'classnames';

const { TreeNode } = Tree;

const rootDir = {
    id: "0",
    key: "0",
    level: 0,
}

const DirMenu = (props, ref) => {

    const {
        projectId,
        docType,
        width,
        enableLevel = 2,
        onSuccess,
        loadDocData,
        deleteDir,
        dirOpertion = [],
        docAction = [],
        onClickDoc,
        updateDocDir,
        onDirTreeData,
        title,
        switcherIcon,
        onClickDir,
        rootMore,
        dirMoreActions,
    } = props;

    const [treeData, setTreeData] = useState([]);
    const [addDirModalVisibleDir, setAddDirModalVisibleDir] = useState()
    const [expandedKeys, setExpandedKeys] = useState([]);
    const [loadedKeys, setLoadedKeys] = useState([]);
    const [addDirDropDownVisible, setAddDirDropDownVisible] = useState({})
    const [actionDropDownVisible, setActionDropDownVisible] = useState({})
    // const [dirDocData, setDirDocData] = useState({})
    const [dirNodeData, setDirNodeData] = useState({})
    const [dragNode, setDragNode] = useState()
    useEffect(() => {
        if (projectId) {
            listDocDirs()
        }
    }, [projectId])

    const expendDirs = (keys) => {
        console.log("expendDirs", keys)
        let addExpendKeys = [];
        keys.forEach(key => {
            let dirNode = dirNodeData[key];
            if (dirNode) {
                let dirRouteKeys = dirNode.routePath.split("_")
                addExpendKeys = [...addExpendKeys, ...dirRouteKeys]
            }
        })
        ArrayUtils.removeAll(addExpendKeys, expandedKeys);
        if (addExpendKeys && addExpendKeys.length > 0) {
            // console.log(addExpendKeys, expandedKeys)
            setExpandedKeys([...expandedKeys, ...addExpendKeys])
        }

    }

    const addDocNode = (dirId, docNode) => {
        console.log("addDocNode", dirId, docNode)
        if (dirId === "0") {
            treeData.push(docNode)
        } else {
            let dirNode = dirNodeData[key];
            dirNode.children.push(docNode)
        }
        setTreeData([...treeData])
    }



    useImperativeHandle(ref, () => ({
        expendDirs, addDocNode
    }))



    useEffect(() => {
        if (expandedKeys && treeData.length > 0) {
            console.log("expandedKeys", expandedKeys, treeData)
            onBatchDocLoad(expandedKeys)
        }
    }, [expandedKeys, treeData])

    useEffect(() => {
        // console.log(treeData)
        if (onDirTreeData) {
            onDirTreeData(treeData)
        }
    }, [treeData])

    const addDirModalShow = (dir) => {
        // console.log(dir)
        setAddDirModalVisibleDir({
            parentDirId: dir.id,
            parandDir: dir
        })
    }

    const addDirSuccess = (dir) => {
        // console.log(dir, addDirModalVisibleDir)
        if (addDirModalVisibleDir.id) {
            // 修改
            addDirModalVisibleDir.title = dir.title
            setTreeData([...treeData])
        } else {
            if (addDirModalVisibleDir.parentDirId === "0") {
                treeData.push(convertDirToTree(rootDir, dir))
                setTreeData([...treeData])
            } else {
                let subDir = addDirModalVisibleDir.parandDir.children || [];
                subDir.push(convertDirToTree(addDirModalVisibleDir.parandDir, dir));
                setTreeData([...treeData])
                if (expandedKeys.indexOf(addDirModalVisibleDir.parandDir.key) < 0) {
                    expandedKeys.push(addDirModalVisibleDir.parandDir.key)
                    setExpandedKeys([...expandedKeys])
                }
            }
        }
        setAddDirModalVisibleDir(false)
        if (onSuccess) {
            onSuccess(dir)
        }
    }


    const listDocDirs = () => {
        listDirs(projectId, docType).then((result) => {
            let treeData = convertDirListToTree(rootDir, result?.data);
            // console.log(treeData)
            if (loadDocData) {
                setTreeData(treeData)
                loadDocData(["0"], (docData) => {
                    (docData["0"] || []).forEach(doc => {
                        treeData.push(doc)
                    })
                    setTreeData([...treeData])
                });
            } else {
                setTreeData(treeData)
            }
        })
    }

    const convertDirToTree = (parentDir, dir) => {
        if (!dir) {
            return;
        }
        let dirNode = {
            id: dir.id,
            title: dir.name,
            key: dir.id,
            level: parentDir.level + 1,
            isDir: true,
            isLeaf: false,
            children: subDir,
            sortNo: dir.sortNo,
            parentDirId: dir.parentDirId,
            routePath: parentDir.routePath ? parentDir.routePath + "_" + dir.id : dir.id
        }
        const subDir = dir?.subDocDir ? convertDirListToTree(dirNode, dir?.subDocDir) : [];
        dirNodeData[dirNode.id] = dirNode
        setDirNodeData(dirNodeData)
        dirNode.children = subDir;
        return dirNode;
    }

    const convertDirListToTree = (parentDir, dirList) => {
        if (!dirList) {
            return [];
        }
        return dirList.map(dir => convertDirToTree(parentDir, dir))
    }

    const findDirsByKeys = (keys) => {
        return keys.map(key => dirNodeData[key]);
    }
    const findDirRoute = (dirItem) => {
        if (dirItem.isDir) {
            if (dirItem.id === "0") {
                return []
            }
            let dirIds = dirItem.routePath.split("_")
            return findDirsByKeys(dirIds)
        } else {
            if (dirItem.dirId === "0") {
                return []
            }
            let dirNode = dirNodeData[dirItem.dirId];
            if (dirNode && dirNode.routePath) {
                let dirIds = dirNode.routePath.split("_")
                return findDirsByKeys(dirIds)
            }
        }
        return [];
    }

    const dirActionMenu = (dirItem) => {
        return <Menu >
            {dirOpertion.map(oper => {
                return <Menu.Item key={oper.key}
                    className={styles.dirActionMenuClass} icon={oper.icon}
                    onClick={() => {
                        if (oper.onClick) {
                            oper.onClick(dirItem, findDirRoute(dirItem).reverse())
                        }
                    }}>
                    {oper.name}
                </Menu.Item>
            })}
            {dirItem.level < enableLevel && <Menu.Item className={styles.dirActionMenuClass} icon={<FolderAddOutlined />} onClick={() => {
                addDirModalShow(dirItem)
            }}>
                新建目录
        </Menu.Item>}
        </Menu>
    };


    const renderAddDirIcon = (dirItem) => {
        return <Dropdown className={styles.addDirDropdown}
            visible={addDirDropDownVisible[dirItem.key]}
            onVisibleChange={(visible) => {
                addDirDropDownVisible[dirItem.key] = visible;
                setAddDirDropDownVisible({ ...addDirDropDownVisible })
            }}
            overlay={dirActionMenu(dirItem)}>
            <div className={styles.addDirIcon}>
                <PlusOutlined />
            </div>
        </Dropdown>
    }

    const expendAllDir = (docItem) => {
        console.log("expandAll", docItem)
        if (docItem) {
            let docExpendList = getDirKeys([docItem]);
            // console.log(docExpendList)
            ArrayUtils.removeAll(docExpendList, expandedKeys);
            setExpandedKeys([...expandedKeys, ...docExpendList])
        } else {
            if (dirNodeData) {
                // console.log(Object.keys(dirNodeData))
                setExpandedKeys(Object.keys(dirNodeData))
            }
        }
    }

    const renameDir = (docItem) => {
        setAddDirModalVisibleDir(docItem)
    }

    const removeDir = (docDir) => {
        Modal.confirm({
            title: "确认删除目录: " + docDir.title + "",
            onOk: () => {
                if (deleteDir) {
                    delete dirNodeData[docDir.id]
                    deleteDir(docDir, (result) => {
                        console.log("deleteDirRet", result)
                        if (result.success) {
                            loopTreeData(treeData, docDir.key, (item, index, arr) => {
                                arr.splice(index, 1);
                            })
                            setTreeData([...treeData]);
                        }
                    })
                }
            }
        })
    }

    const getDirKeys = (dirTreeNodeList) => {
        if (dirTreeNodeList) {
            let treeNodeKeys = []
            dirTreeNodeList.forEach(dir => {
                treeNodeKeys.push(dir.key)
                if (dir.children) {
                    treeNodeKeys = [...treeNodeKeys, ...getDirKeys(dir.children)]
                }
            })
            return treeNodeKeys;
        }
        return [];
    }

    const canDrop = ({ dropNode, dropPosition }) => {
        // 这里的 dropPosition == 0 是子节点
        // console.log( dropNode, dropPosition,dragNode)
        if (dragNode.isDir) {
            if (dropNode.level == enableLevel && dropPosition === 0) {
                return false;
            }
            return dropNode.isDir;
        } else {
            return dropNode.isDir
        }
    }

    const loopTreeData = (data, key, callback) => {
        for (let i = 0; i < data.length; i++) {
            if (data[i].key === key) {
                return callback(data[i], i, data);
            }
            if (data[i].children) {
                loopTreeData(data[i].children, key, callback);
            }
        }
    };

    const onDrop = (dropData) => {
        setDragNode(null)
        const { event, node, dragNode, dragNodesKeys, dropPosition } = dropData;
        const dropPos = node.pos.split('-');
        let relDropPosition = dropPosition - Number(dropPos[dropPos.length - 1]);

        // console.log(event, node, dragNode, dragNodesKeys, relDropPosition)
        if (node.children && node.children.length > 0 && dragNode.children && dragNode.children.length > 0) {
            message.error(`移动之后，目录层级大于${enableLevel}层,不能移动`);
            return;
        }
        loopTreeData(treeData, dragNode.key, (item, index, arr) => {
            arr.splice(index, 1);
        })
        let sortNo = 0, parentDirId;
        if (relDropPosition === 1) {
            parentDirId = node.parentDirId
            // 同级节点
            loopTreeData(treeData, node.key, (item, index, arr) => {
                if (index < (arr.length - 1)) {
                    sortNo = (item.sortNo + arr[index + 1].sortNo) / 2
                } else {
                    sortNo = item.sortNo + 65536;
                }
                arr.splice(index + 1, 0, dragNode);
            })
        } else if (relDropPosition === 0) {
            parentDirId = node.id;
            // 子节点
            node.children = node.children || [];
            if (node.children.length > 0) {
                sortNo = node.children[0].sortNo / 2;
            }
            node.children.unshift(dragNode);
        }
        dragNode.parentDirId = parentDirId
        dragNode.sortNo = sortNo;
        let parentDir = dirNodeData[parentDirId]
        // console.log(parentDir,parentDirId,dirNodeData)
        if (parentDir) {
            dragNode.routePath = parentDir.routePath + "_" + dragNode.key
        } else {
            dragNode.routePath = dragNode.key
        }
        setTreeData([...treeData]);
        if (dragNode.isDir) {
            updateDir(projectId, dragNode.id, {
                parentDirId: parentDirId,
                sortNo: sortNo
            }).then((result) => {
                if (result?.success) {
                    message.success("移动成功")
                }
            })
        } else {
            if (updateDocDir) {
                updateDocDir(dragNode.id, {
                    dirId: parentDirId,
                    sortNo: sortNo
                })
            }
        }
    }

    const onBatchDocLoad = (keys) => {
        let needLoadKeys = [...keys]
        ArrayUtils.removeAll(needLoadKeys, loadedKeys);
        if (needLoadKeys.length === 0) {
            return;
        }
        needLoadKeys.forEach((key => {
            loadedKeys.push(key);
        }))
        if (loadDocData) {
            loadDocData(needLoadKeys, (docData) => {
                // console.log(needLoadKeys,docData)
                needLoadKeys.forEach((key => {
                    (docData[key] || []).forEach(doc => {
                        if (dirNodeData[key].children) {
                            dirNodeData[key].children.push(doc)
                        } else {
                            dirNodeData[key].children = [doc]
                        }
                    })
                }))
                // setDirDocData({ ...dirDocData })
                setLoadedKeys([...loadedKeys])
                // console.log(treeData)
                // 这里很奇怪同步设置不能触发重新渲染树节点
                setTreeData([...treeData])
                setExpandedKeys([...expandedKeys])

            });

        }
    }

    const renderDirActions = (docItem) => {
        let actions = [];
        if (dirMoreActions) {
            actions = [...dirMoreActions];
        } else {
            actions = ["rename", "expend", "delete"]
        }
        actions = actions.map(action => {
            if (typeof action === "string") {
                if (action === "rename") {
                    return <div key="rename" onClick={() => {
                        renameDir(docItem)
                    }}>重命名</div>
                }
                if (action === "expend") {
                    return <div key="expend" onClick={() => {
                        expendAllDir(docItem)
                    }}>展开</div>
                }
                if (action === "delete") {
                    return <div className={styles.deleteDirItem} key="delete"
                        onClick={() => {
                            removeDir(docItem)
                        }} >删除</div>
                }
            } else {
                return action
            }
        })
        return actions;
    }

    const docTitleRender = (docItem) => {
        if (docItem.isDir) {
            let operationClassName = classNames(styles.dirOperation, {
                [styles.operationVisible]: (!addDirDropDownVisible[docItem.key]) && (!actionDropDownVisible[docItem.key])
            })
            return <div className={styles.dirItem}>
                <div className={styles.dirItemTitle} onClick={() => {
                    if (onClickDir) {
                        onClickDir(docItem, findDirRoute(docItem))
                    }
                }}>
                    {docItem.title}
                </div>
                <div className={operationClassName}>
                    <Space size={2}>
                        {renderAddDirIcon(docItem)}
                        <ActionDropdown
                            handleVisibleChange={(visible) => {
                                actionDropDownVisible[docItem.key] = visible;
                                setActionDropDownVisible({ ...actionDropDownVisible })
                            }}
                            actions={renderDirActions(docItem)}
                            icon="more"
                            actionItemClassName={styles.dirActionMenuClass}
                            iconClassName={styles.addDirIcon}
                        ></ActionDropdown>
                    </Space>
                </div>
            </div>
        }
        let operationClassName = classNames(styles.dirOperation, {
            [styles.operationVisible]: (!addDirDropDownVisible[docItem.key]) && (!actionDropDownVisible[docItem.key])
        })
        return <div className={styles.dirItem}>
            <div className={styles.dirItemTitle} onClick={() => {
                if (onClickDoc) {
                    onClickDoc(docItem, findDirRoute(docItem))
                }
            }}>
                {docItem.title || "未命名"}
            </div>
            <div className={operationClassName}>
                <Space size={2}>
                    <ActionDropdown
                        handleVisibleChange={(visible) => {
                            actionDropDownVisible[docItem.key] = visible;
                            setActionDropDownVisible({ ...actionDropDownVisible })
                        }}
                        actions={docAction}
                        icon="more"
                        actionItemClassName={styles.dirActionMenuClass}
                        iconClassName={styles.addDirIcon}
                    ></ActionDropdown>
                </Space>
            </div>
        </div>
    }

    const renderSwitchButton = () => {
        if (switcherIcon) {
            return switcherIcon;
        }
        if (switcherIcon === null) {
            return <></>
        }
        return <CaretDownOutlined className={styles.treeNodeIcon} />
    }

    return (<div className={styles.docMenuBody} style={{
        width: width || "200px"
    }}>
        <div className={styles.rootTitle}>
            {title}
            <div className={styles.rootOperation}>
                <Space size={2} align="center">
                    {renderAddDirIcon({
                        id: "0",
                        level: 0
                    })}
                    <div style={{ height: "22px" }}>
                        {rootMore || <ActionDropdown
                            icon="more"
                            actions={[
                                <div key="expendAll" onClick={() => expendAllDir()}>展开</div>
                            ]}
                            actionItemClassName={styles.dirActionMenuClass}
                            iconClassName={styles.addDirIcon}
                        ></ActionDropdown>}
                    </div>
                </Space>
            </div>
        </div>
        <Tree
            switcherIcon={renderSwitchButton()}
            draggable={true}
            allowDrop={canDrop}
            onDragStart={({ event, node }) => {
                setDragNode(node)
            }}
            onDrop={onDrop}
            blockNode={true}
            titleRender={docTitleRender}
            selectable={false}
            expandedKeys={expandedKeys}
            onExpand={(keys, data) => {
                // console.log(keys,data)
                setExpandedKeys(keys)
            }}
            treeData={treeData}>

        </Tree>

        <DirFormModal
            docType={docType}
            projectId={projectId}
            visibleDir={addDirModalVisibleDir}
            onSuccess={addDirSuccess}
            onCancel={() => {
                setAddDirModalVisibleDir(false)
            }}
        >
        </DirFormModal>
    </div>)
}

export default forwardRef(DirMenu)